package com.ray.test.runner;

import com.ray.test.annotation.InitObject;
import com.ray.test.annotation.InitValue;
import com.ray.test.annotation.Proxy;
import com.ray.test.hander.MockHander;
import com.ray.test.hander.MockHanderContent;
import com.ray.test.proxy.ProxyBean;
import com.ray.test.util.PropertyUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.InitializationError;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author bo shen
 * @Description: 通用mock单元测试
 * @Class: RAutoSpringJUnit4ClassRunner
 * @Package test.runner
 * @date 2019/9/29 8:45
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
public class RAutoSpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {

    /***需要代理执行的对象**/
    private static ThreadLocal<Object> proxys = new ThreadLocal<>();
    /***需要代理执行的对象**/
    private static ThreadLocal<Class> runClass = new ThreadLocal<>();
    /***需要代理执行的对象**/
    private static ThreadLocal<Object> tests = new ThreadLocal<>();
    /***需要排除的方法***/
    private static ThreadLocal<List<String>> exclude = new ThreadLocal<>();
    /***外部提供的bean**/
    private static ThreadLocal<Map<Class<?>,Object>> beans = new ThreadLocal<>();
    /***外部提供的配置**/
    private static ThreadLocal<Map<String,Object>> values = new ThreadLocal<>();
    public RAutoSpringJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
        createManager(clazz);
    }

    /***
     * 创建管理器
     * @param clazz
     */
    private void createManager(Class<?> clazz) {
        try {
            //测试对象
            Object test = getTestClass().getJavaClass().newInstance();
            tests.set(test);
            initObject(clazz,test);
            initValue(clazz,test);
        } catch (Exception e) {
            log.info("容器启动异常");
        }
    }

    private void initObject(Class<?> clazz,Object test) {
        try {
            Map<Class<?>,Object> beanServices = new HashMap<>();
            List<FrameworkField> frameworkFields = getTestClass().getAnnotatedFields(InitObject.class);
            for (FrameworkField frameworkField : frameworkFields) {
                beanServices.put(frameworkField.getType(), PropertyUtils.readProperty(test, frameworkField.getName()));
            }
            beans.set(beanServices);
        } catch (Exception e) {
            log.info("属性设置异常", e);
        }
    }

    private void initValue(Class<?> clazz,Object test) {
        try {
            Map<String,Object> valueServices = new HashMap<>();
            List<FrameworkField> frameworkFields = getTestClass().getAnnotatedFields(InitValue.class);
            for (FrameworkField frameworkField : frameworkFields) {
                valueServices.put(frameworkField.getAnnotation(InitValue.class).name(), PropertyUtils.readProperty(test, frameworkField.getName()));
            }
            values.set(valueServices);
        } catch (Exception e) {
            log.info("属性设置异常", e);
        }
    }

    @Override
    public Object createTest() throws Exception {
        //初始化属性
        List<FrameworkField> frameworkFields = getTestClass().getAnnotatedFields(Proxy.class);
        try {
            for (FrameworkField frameworkField : frameworkFields) {
                //初始化对象
                Proxy proxy = frameworkField.getAnnotation(Proxy.class);
                Object proxyBean = proxy.implClass().newInstance();
                //创建mock数据
                proxyBean = new ProxyBean(proxyBean,beans.get(),values.get()).create(false);
                proxys.set(proxyBean);
                runClass.set(frameworkField.getType());
                //设置排除的方法
                exclude.set(Arrays.asList(proxy.excluedName()));
            }
        } catch (InstantiationException e) {
            log.info("属性设置异常", e);
        } catch (IllegalAccessException e) {
            log.info("属性设置异常", e);
        }
        return tests.get();
    }

    /**
     * 最后执行方法
     * @param
     * @return
     */
    public static int test(){
        MockHanderContent handerContent = new MockHanderContent();
        handerContent.setRunClasss(runClass.get());
        handerContent.setExcludeMethodName(exclude.get());
        handerContent.setRunTarget(proxys.get());
        return test(handerContent);
    }

    /**
     * @param
     * @return
     */
    public static int test(String ...methodName){
        MockHanderContent handerContent = new MockHanderContent();
        handerContent.setRunClasss(runClass.get());
        handerContent.setIncludeMethodName(Arrays.asList(methodName));
        handerContent.setRunTarget(proxys.get());
        return test(handerContent);
    }

    /**
     * 最后执行方法
     * @param
     * @return
     */
    private static int test(MockHanderContent handerContent){
        return new MockHander(handerContent).runTest();
    }

}
